package com.gmall.batch.gmallbatch.aop;

import com.gmall.common.enums.DbEnum;
import com.gmall.batch.gmallbatch.anno.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author HL.Wu
 * @date 2020/6/22 11:33
 * Copyright ©www.sioo.cn Copyright@2009-2020 AII Right Reserve
 */
@Aspect
@Component
@Slf4j
public class DynamicDataSourceAspect {

    @Pointcut("execution( * com.gmall.batch.gmallbatch.biz.*.*(..))")
    private void bizPackage(){}

    //定义切入点
    @Pointcut("bizPackage()")
    public void dataSourcePointCut() {
    }


    @Before("dataSourcePointCut()")
    public void beforeSwitchDS(JoinPoint point){
        // 获得当前访问的class
        Class<?> className = point.getTarget().getClass();
        // 获得访问的方法名
        String methodName = point.getSignature().getName();
        // 获取参数的类型
        Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
        //设置默认源
        DbEnum dataSource = DataSourceContextHolder.DEFAULT_DB;
        try {
            // 得到访问的方法对象
            Method method = className.getMethod(methodName, argClass);
            // 判断是否存在操作数据库注解，如果没有则默认为主数据库
            if (method.isAnnotationPresent(DataSource.class)) {
                DataSource annotation = method.getAnnotation(DataSource.class);
                // 取出注解中的数据源名
                dataSource = annotation.value();
            }
            log.warn("start to switch database ,get database info is [{}]",dataSource.name());
        } catch (Exception e) {
            log.error("switch database occur error , the error message is [{}]",e);
        }
        // 切换数据源
        DataSourceContextHolder.setDB(dataSource);
    }

    @After("dataSourcePointCut()")
    public void afterSwitchDS(JoinPoint point){
        log.warn("start to clear database [{}]",DataSourceContextHolder.getDB());
        // clear thread local info
        DataSourceContextHolder.clearDB();
    }
}